package com.bj58.mis.apm.server.kylinreceive.service.impl;

import com.bj58.mis.apm.server.core.util.TimesUtil;
import com.bj58.mis.apm.server.kylinreceive.mapper.WarnMapper;
import com.bj58.mis.apm.server.kylinreceive.model.KylinCube;
import com.bj58.mis.apm.server.kylinreceive.model.KylinLog;
import com.bj58.mis.apm.server.kylinreceive.model.KylinSegment;
import com.bj58.mis.apm.server.kylinreceive.model.KylinWarn;
import com.bj58.mis.apm.server.kylinreceive.service.WarnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Author: wangxw
 * @Date: 2018/10/12 18:57
 */
@Service
@Transactional
public class WarnServiceImpl implements WarnService {

    @Autowired
    private WarnMapper warnMapper;

    //'cube_slow_query','cube_job_time','cube_warn_swell'
    @Override
    public void checkBuild(List<Map<String,Object>> jobs) {
        Double item = warnMapper.queryDictionaryItem("cube_job_time");
        String warnTimes = TimesUtil.formatTimes(item.longValue());
        Date last = warnMapper.queryLastTime("build");
        List<KylinWarn> list = new ArrayList<>();
        jobs.forEach(job -> {
            if((last == null || ((Number)job.get("last_modified")).longValue() > last.getTime()) && ((Number)job.get("duration")).doubleValue() > item) {
                KylinWarn kw = new KylinWarn();
                kw.setCubeId((String)job.get("cubeId"));
                kw.setWarnType("build");
                kw.setWarnTime(new Date(((Number)job.get("last_modified")).longValue()));
                kw.setWarnContext("构建时间" + TimesUtil.formatTimes(((Number)job.get("duration")).longValue()) + "超出预警值" + warnTimes + "，请关注。");
                list.add(kw);
            }
        });
        if(list.size() > 0){
            warnMapper.saveWarn(list);
        }
    }

    @Override
    public void checkSwell(List<KylinSegment> list, KylinCube kylinCube) {
        Double item = warnMapper.queryDictionaryItem("cube_warn_swell");
        Date last = warnMapper.queryLastTime("build");

        Long size = 0L;
        Long inputSize = 0L;
        for(KylinSegment seg : list) {
            if(seg.getSize() != null && seg.getInputRecordsSize() != null) {
                size += seg.getSize();
                inputSize += seg.getInputRecordsSize();
            }
        }
        if(size > 0 && inputSize > 0) {
            Double swell = size.doubleValue() / inputSize;
            if (swell.doubleValue() > item && (last == null || kylinCube.getLastModified().getTime() > last.getTime())){
                KylinWarn kw = new KylinWarn();
                kw.setCubeId(list.get(0).getCubeId());
                kw.setWarnType("swell");
                kw.setWarnTime(kylinCube.getLastModified());
                kw.setWarnContext("膨胀倍数" + new BigDecimal(swell).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue() + "超过超出预警值" + item.longValue() + "，请关注。");
                List<KylinWarn> ws = new ArrayList<>();
                ws.add(kw);
                warnMapper.saveWarn(ws);
            }
        }
    }

    @Override
    public void checkQuery(List<KylinLog> logList) {
        Double item = warnMapper.queryDictionaryItem("cube_slow_query");
        Map<String, KylinWarn> map = new HashMap<>();
        logList.forEach(log -> {
            if(log.getCubeId() != null && log.getDuration().doubleValue() > item.doubleValue()) {
                KylinWarn kw = map.get(log.getCubeId());
                if(kw == null){
                    kw = new KylinWarn();
                    kw.setCubeId(log.getCubeId());
                    kw.setWarnType("query");
                    kw.setWarnTime(log.getQueryTime());
                    kw.setWarnContext("查询响应时间" + log.getDuration().doubleValue() + "s超出预警值" + item.doubleValue() + "s，请关注。");
                    map.put(log.getCubeId(), kw);
                }
            }
        });
        if(map.size() > 0){
            warnMapper.saveWarn(map.values());
        }
    }

    @Override
    public void checkUsed() {
        warnMapper.checkCubeUnused();
    }

}
